﻿using System.Windows;
using System.Collections.Generic;
using System;
using System.Windows.Input;
using DSPL.Services;
using DSPL.Contracts;
using DSPL.Common;
using System.Data;
using DSPL.Services.Services;
using DSPL.Contracts.Common;
using DSPL.Contracts.ViewModel;
using DSPL.Contracts.Command;
using DSPL.Finac.Common;
using DSPL.Common.Classes;
using DSPL.Contracts.Interfaces;
using DSPL.Services.Rules;

namespace DSPL.Finac.ViewModel
{
    public class GoodReceiveReturnViewModel : BaseViewModel
    {
        private bool isReferenceNoFocused;       
        private bool isCurrencyCodeFocused;
        private bool isSupplierCodeFocused;
        private bool isLocationCodeFocused;
        private bool isCostCodeFocused;
        private bool isExchangeRateFocused;
        private bool isTransactionDateFocused;
        private DataRow drGrnRow;
        private DataRow drItemRow;
        private ICommand refreshCurrencyData;
        private ICommand calculation;
        private ICommand itemCodeGotFocus;
        private string _refNoFilterExpression;
        private Visibility isPurchaseOrderNoVisible;
        private bool isPurchaseOrderNoMandatory;
        private bool isCurrencyCodeEnabled;
        private bool isExchangeRateEnabled;
        private DataTable _dtGrnrTax;
        private string _itemCodeFilter;
        private int grnIndex;

        #region Define properties
       
        public bool IsCurrencyCodeFocused
        {
            get { return isCurrencyCodeFocused; }
            set
            {
                isCurrencyCodeFocused = value;
                this.OnPropertyChanged("IsCurrencyCodeFocused");
            }
        }

        public bool IsSupplierCodeFocused
        {
            get { return isSupplierCodeFocused; }
            set
            {
                isSupplierCodeFocused = value;
                this.OnPropertyChanged("IsSupplierCodeFocused");

            }
        }

        public bool IsLocationCodeFocused
        {
            get { return isLocationCodeFocused; }
            set
            {
                isLocationCodeFocused = value;
                this.OnPropertyChanged("IsLocationCodeFocused");

            }
        }

        public bool IsCostCodeFocused
        {
            get { return isCostCodeFocused; }
            set
            {
                isCostCodeFocused = value;
                this.OnPropertyChanged("IsCostCodeFocused");

            }
        }

        public bool IsExchangeRateFocused
        {
            get { return isExchangeRateFocused; }
            set
            {
                isExchangeRateFocused = value;
                this.OnPropertyChanged("IsExchangeRateFocused");

            }
        }

        public bool IsTransactionDateFocused
        {
            get { return isTransactionDateFocused; }
            set
            {
                isTransactionDateFocused = value;
                this.OnPropertyChanged("IsTransactionDateFocused");

            }
        }

        public bool IsReferenceNoFocused
        {
            get { return isReferenceNoFocused; }
            set
            {
                isReferenceNoFocused = value;
                this.OnPropertyChanged("IsReferenceNoFocused");
            }
        }

        public DataRow GrnSelectedRow
        {
            get
            {
                return drGrnRow;
            }
            set
            {
                drGrnRow = value;
                OnPropertyChanged("GrnSelectedRow");
            }
        }

        public DataRow ItemSelectedRow
        {
            get
            {
                return drItemRow;
            }
            set
            {
                drItemRow = value;
                OnPropertyChanged("ItemSelectedRow");
            }
        }
                
        public string RefNoFilterExpression
        {
            get
            {
                return _refNoFilterExpression;
            }
            set
            {
                _refNoFilterExpression = value;
                OnPropertyChanged("RefNoFilterExpression");
            }
        }

        public Visibility IsPurchaseOrderNoVisible
        {
            get
            {
                return isPurchaseOrderNoVisible;
            }
            set
            {
                isPurchaseOrderNoVisible = value;
                OnPropertyChanged("IsPurchaseOrderNoVisible");
            }
        }               

        public bool IsPurchaseOrderNoMandatory
        {
            get
            {
                return isPurchaseOrderNoMandatory;
            }
            set
            {
                isPurchaseOrderNoMandatory = value;
                OnPropertyChanged("IsPurchaseOrderNoMandatory");
            }
        }

        public bool IsCurrencyCodeEnabled
        {
            get
            {
                return isCurrencyCodeEnabled;
            }

            set
            {
                isCurrencyCodeEnabled = value;
                this.OnPropertyChanged("IsCurrencyCodeEnabled");
            }
        }


        public bool IsExchangeRateEnabled
        {
            get
            {
                return isExchangeRateEnabled;
            }

            set
            {
                isExchangeRateEnabled = value;
                this.OnPropertyChanged("IsExchangeRateEnabled");
            }
        }

        public string ItemCodeFilter
        {
            get
            {
                return _itemCodeFilter;
            }
            set
            {
                _itemCodeFilter = value;
                this.OnPropertyChanged("ItemCodeFilter");
            }
        }

        public int GrnRowIndex
        {
            get
            {
                return grnIndex;
            }
            set
            {
                grnIndex = value;
                OnPropertyChanged("GrnRowIndex");
            }
        }

        #endregion


        #region Constructor

        public GoodReceiveReturnViewModel()
            : base()
        {
            MessageTitle = "Good Receive Note Return";
            RefGenCode = "SGRNR";
           
        }

        #endregion

        # region Commands

        public ICommand RefreshCurrencyData
        {
            get
            {
                if (this.refreshCurrencyData == null)
                {
                    this.refreshCurrencyData = new RelayCommand(RefreshCurrencyDataExecuted);
                }
                return this.refreshCurrencyData;
            }
        }

        public ICommand Calculation
        {
            get
            {
                if (this.calculation == null)
                {
                    this.calculation = new RelayCommand(CalculateAmountsExecuted);
                }
                return this.calculation;
            }
        }

        public ICommand ItemCodeGotFocus
        {
            get
            {
                if (this.itemCodeGotFocus == null)
                {
                    this.itemCodeGotFocus = new RelayCommand(ItemCodeGotFocusExecuted);
                }
                return this.itemCodeGotFocus;
            }
        }

        #endregion

        /// <summary>
        /// Validate mandatory data before save
        /// </summary>
        /// <param name="obj"></param>
        protected override void PreDataValidateExecuted(object obj)
        {           
            IsCurrencyCodeFocused = false;
            IsSupplierCodeFocused = false;
            IsLocationCodeFocused = false;
            IsCostCodeFocused = false;
            IsExchangeRateFocused = false;
            IsTransactionDateFocused = false;
            IsReferenceNoFocused = false;

            var messageService = new MessageService();
            var masterReadService = new MasterReadService();
            if (FormMode != Modes.New)
            {
                if (CurrentRow["RefNo"].ToString().Trim() == string.Empty)
                {
                    messageService.ShowMessage(MessageText.ReferenceNoNotEmpty, MessageTitle, MessageType.InfoOK);
                    IsReferenceNoFocused = true;
                    this.IsValid = false;
                    return;
                }
            }

            if (CurrentRow["TxnDate"] == DBNull.Value)
            {
                messageService.ShowMessage(MessageText.TransactionDateNotEmpty, MessageTitle, MessageType.InfoOK);
                IsTransactionDateFocused = true;
                this.IsValid = false;
                return;
            }
            else
            {
                var stockRules = new StockRulesService();
                if (!stockRules.ValidateStockTransactionDate(Convert.ToDateTime(CurrentRow["TxnDate"]), CurrentRow["RefNo"].ToString().Trim(), BlockBackDatedTransaction, ReportGroup))
                {                   
                   IsTransactionDateFocused = true;
                   this.IsValid = false;
               }
                
            }

            if (CurrentRow["SupplierPk"] == DBNull.Value || Convert.ToInt32(CurrentRow["SupplierPk"]) == 0)
            {
                messageService.ShowMessage(MessageText.SupplierNotEmpty, MessageTitle, MessageType.InfoOK);
                IsSupplierCodeFocused = true;
                this.IsValid = false;
                return;
            }
            else
            {
                if (!masterReadService.IsSupplierActive(Convert.ToInt32(CurrentRow["SupplierPk"])))
                {
                    messageService.ShowMessage(MessageText.SupplierNotActive, MessageTitle, MessageType.InfoOK);
                    IsSupplierCodeFocused = true;
                    this.IsValid = false;
                    return;
                }
            }

            if (CurrentRow["LocationPk"] == DBNull.Value || Convert.ToInt32(CurrentRow["LocationPk"]) == 0)
            {
                messageService.ShowMessage(MessageText.LocationNotEmpty, MessageTitle, MessageType.InfoOK);
                IsLocationCodeFocused = true;
                this.IsValid = false;
                return;
            }

            if (CurrentRow["CostPk"] == DBNull.Value || Convert.ToInt32(CurrentRow["CostPk"]) == 0)
            {
                messageService.ShowMessage(MessageText.CostCodeNotEmpty, MessageTitle, MessageType.InfoOK);
                IsCostCodeFocused = true;
                this.IsValid = false;
                return;
            }

            if (CurrentRow["CurPk"] == DBNull.Value || Convert.ToInt32(CurrentRow["CurPk"]) == 0)
            {
                messageService.ShowMessage(MessageText.CurrencyCodeNotEmpty, MessageTitle, MessageType.InfoOK);
                IsCurrencyCodeFocused = true;
                this.IsValid = false;
                return;
            }

            if (CurrentRow["CurRate"] == DBNull.Value || Convert.ToInt32(CurrentRow["CurRate"]) == 0)
            {
                messageService.ShowMessage(MessageText.CurrencyRateNotZero, MessageTitle, MessageType.InfoOK);
                IsExchangeRateFocused = true;
                this.IsValid = false;
                return;
            }

            if (DtChildTransaction.Select("GrnPk<>0 AND (PurPrice> 0.00 AND qty >0.00)").Length == 0)
            {
                messageService.ShowMessage(MessageText.NoValidData, MessageTitle, MessageType.InfoOK);
                this.IsValid = false;
                return;
            }

            for (int i = DtChildTransaction.Rows.Count - 1; i >= 0; i--)
            {
                if (string.IsNullOrEmpty(DtChildTransaction.Rows[i]["ItemCode"].ToString()) || (DtChildTransaction.Rows[i]["Qty"]) == DBNull.Value || (DtChildTransaction.Rows[i]["PurPrice"]) == DBNull.Value)
                    DtChildTransaction.Rows[i].Delete();
            }
            DtChildTransaction.AcceptChanges();

            CalculateAmounts();

            if (!CheckItemStatus())
            {
                this.IsValid = false;
                return;
            }

            if (DtChildTransaction.Select("ItemCode <>'' AND (GrnPk=0 Or PurPrice<=0.00 Or qty <=0.00)").Length > 0)
            {
                var messageResult = messageService.ShowMessage(MessageText.InvalidGridRecordOmit, MessageTitle, MessageType.QuizOKCancel);

                if (messageResult == MessageBoxResult.No)
                {
                    this.IsValid = false;
                    return;
                }

            }
            
            double currencyRate = Convert.ToDouble(CurrentRow["CurRate"]);
            int grnPk = 0;
            int itemPk = 0;
            double bTotalAmount=0.00, bTotalDis=0.00, bTotalTax=0.00;
            foreach (DataRow drDataDetail in DtChildTransaction.Rows)
            {
                grnPk = Convert.ToInt32(drDataDetail["GrnPk"]);
                itemPk = Convert.ToInt32(drDataDetail["ItemPk"]);
                drDataDetail["TxnDate"] = CurrentRow["TxnDate"];
                
                drDataDetail["TxnType"] = "12";

                drDataDetail["BTaxAmt"] = (drDataDetail["TaxAmt"] != DBNull.Value ? Math.Round(Convert.ToDouble(drDataDetail["TaxAmt"]) * currencyRate, 2) : 0.00);               
                drDataDetail["BDisAmt"] = (drDataDetail["DisAmt"] != DBNull.Value ? Math.Round(Convert.ToDouble(drDataDetail["DisAmt"]) * currencyRate, 2) : 0.00);               
                drDataDetail["BAmt"] = (drDataDetail["Amt"] != DBNull.Value ? Math.Round(Convert.ToDouble(drDataDetail["Amt"]) * currencyRate, 2) : 0.00);               
                
                bTotalTax = bTotalTax + (drDataDetail["TaxAmt"] != DBNull.Value ? Math.Round(Convert.ToDouble(drDataDetail["TaxAmt"]) * currencyRate, 2) : 0.00);
                bTotalAmount = bTotalAmount + (drDataDetail["Amt"] != DBNull.Value ? Math.Round(Convert.ToDouble(drDataDetail["Amt"]) * currencyRate, 2) : 0.00);
                bTotalDis = bTotalDis + (drDataDetail["DisAmt"] != DBNull.Value ? Math.Round(Convert.ToDouble(drDataDetail["DisAmt"]) * currencyRate, 2) : 0.00);

                foreach(DataRow drGrrTaxRow in _dtGrnrTax.Rows)
                {
                    if (Convert.ToInt32(drGrrTaxRow["ItemPk"]) == itemPk || (Convert.ToInt32(drGrrTaxRow["GrnPk"])==grnPk))
                    {
                         drGrrTaxRow["BTaxDetAmt"]  = (drDataDetail["TaxDetAmt"] != DBNull.Value ? Math.Round(Convert.ToDouble(drDataDetail["TaxDetAmt"]) * currencyRate, 2) : 0.00);
                    }
                }
            }

            CurrentRow["TxnType"] = "12";
            CurrentRow["BTotalDis"] = bTotalDis;
            CurrentRow["BTotalTax"] = bTotalTax;
            CurrentRow["BTotalAmt"] = bTotalAmount;
            CurrentRow["prtCopy"] = 0;
            
            this.IsValid = true;
        }

        protected override void RefreshExternalDataObjectsExecueted(object obj)
        {

            base.RefreshExternalDataObjectsExecueted(obj);          

            if (FormMode == Modes.New)
            {
                var masterReadService = new MasterReadService();
                CurrentRow["TxnDate"] = DateTime.Now;
                                
                CurrentRow["CurPk"] = masterReadService.GetCurrencyKey(GlobalVariables.BaseCurrency);
                CurrentRow["CurRate"] = 1.00;

                var commonReadService = new CommonReadService();
                CurrentRow["CostPk"] = commonReadService.GetUserWiseCostCenter();
                CurrentRow["LocationPk"] = commonReadService.GetUserWiseLocation();
                OnPropertyChanged("CurrentRow");
            }

            if (FormMode != Modes.None)
            {
                var transactionReadService = new TransactionReadService();
                int primaryKey = (CurrentRow["GrnrPk"] == DBNull.Value ? 0 : Convert.ToInt32(CurrentRow["GrnrPk"]));
                _dtGrnrTax = transactionReadService.GetGoodReceiveReturnTaxData(primaryKey);
            }

        }        

        protected override void EnableDisableSpecificControls()
        {
            base.EnableDisableSpecificControls();

            if (GlobalVariables.SystemCurrency.Trim().ToUpper() == "LOCAL")
            {
                IsCurrencyCodeEnabled = false;
                IsExchangeRateEnabled = false;
            }
            else
            {
                IsCurrencyCodeEnabled = IsExchangeRateEnabled = ((FormMode == Modes.New || FormMode == Modes.Edit) ? true : false);
               
            }
        }

        private void RefreshCurrencyDataExecuted(object obj)
        {
            TxtCurrency txtCurrency = (TxtCurrency)obj;
            CurrentRow["CurRate"] = txtCurrency.CurrencyRate;
            this.OnPropertyChanged("CurrentRow");
        }

        protected override void AddAddionalReportParametersExecuted(object obj)
        {
            base.AddAddionalReportParametersExecuted(obj);

            if (AdditionalReportParameters == null)
            {
                AdditionalReportParameters = new List<IReportParameters>();
            }
            AdditionalReportParameters.Add(new ReportParameters() { ParameterIndex = 8, ParameterName = "VatCompanyTaxNo", InputValue = GlobalVariables.VatCompanyTaxNo });
        }

        private void CalculateAmountsExecuted(object obj)
        {
            CalculateAmounts();
        }

        private void CalculateAmounts()
        {
            double curRate = Convert.ToDouble(CurrentRow["CurRate"]);
            string itemCode;
            double costPrice,purchasePrice,  quantity, totalValue, totalBValue, totalDiscount, totalBDiscount, discount, total, totalB, sumTotalDiscount, sumTotal;
            double totalTax, totAmount;
            totalTax = totAmount = 0.00;

            int noOfDecimalPlaces = GlobalVariables.CurValDecimalPoints;
            int noOfAvgRateDecimal = GlobalVariables.AverageRateDecimal;

            int sequenceNo = 1;
            sumTotalDiscount = sumTotal = 0.00;           

            foreach (DataRow drDataRow in DtChildTransaction.Rows)
            {
                itemCode = Convert.ToString(drDataRow["ItemCode"]);
                costPrice = (drDataRow["CostPrice"] == DBNull.Value ? 0.00 : Convert.ToDouble(drDataRow["CostPrice"]));
                purchasePrice = (drDataRow["PurPrice"] == DBNull.Value ? 0.00 : Convert.ToDouble(drDataRow["PurPrice"]));

                quantity = (drDataRow["Qty"] == DBNull.Value ? 0.00 : Convert.ToDouble(drDataRow["Qty"]));
                discount = (drDataRow["DisPer"] == DBNull.Value ? 0.00 : Convert.ToDouble(drDataRow["DisPer"]));

                if (itemCode == string.Empty || purchasePrice == 0.00 || quantity == 0.00)
                {
                    drDataRow["DisAmt"] = 0.00;
                    drDataRow["BDisAmt"] = 0.00;
                    drDataRow["Amt"] = 0.00;
                    drDataRow["BAmt"] = 0.00;
                    drDataRow["SeqNo"] = 0;                    
                    continue;
                }                                
                                
                totalValue = Math.Round(quantity * purchasePrice, noOfDecimalPlaces);
                //totalBValue = Math.Round(quantity * costPrice, noOfDecimalPlaces);
                totalDiscount = Math.Round((totalValue * discount) / 100, noOfDecimalPlaces);
                totalBDiscount = Math.Round(totalDiscount * curRate, noOfDecimalPlaces);

                total = Math.Round(totalValue - totalDiscount, noOfDecimalPlaces);
                totalB = Math.Round(total * curRate, noOfDecimalPlaces);

                drDataRow["DisAmt"] = totalDiscount;
                drDataRow["BDisAmt"] = totalBDiscount;
                drDataRow["Amt"] = total;
                drDataRow["BAmt"] = totalB;
                drDataRow["SeqNo"] = sequenceNo;
                sequenceNo += 1;
                sumTotalDiscount += totalDiscount;
                sumTotal += total;
            }


            CommonRules commonRulesObj = new CommonRules();
            totalTax = totAmount = 0.00;
            DataView viewChildTran = new DataView(DtChildTransaction);

            DataTable dtCopyChildTransaction = viewChildTran.ToTable("dtCopyChildTransaction", false, "GrnrPk", "ItemPk", "Amt", "TaxComPk",  "PurPrice", "Qty", "BAmt", "TaxAmt", "BTaxAmt");
            dtCopyChildTransaction.Columns.Add("RefNo1", typeof(Int32));
            DataView viewGrnTax = new DataView(_dtGrnrTax);

            for (int i = dtCopyChildTransaction.Rows.Count - 1; i >= 0; i--)
            {
                if ((dtCopyChildTransaction.Rows[i]["ItemPk"]==DBNull.Value) || (dtCopyChildTransaction.Rows[i]["Qty"]) == DBNull.Value || (dtCopyChildTransaction.Rows[i]["PurPrice"]) == DBNull.Value)
                    dtCopyChildTransaction.Rows[i].Delete();
            }
            dtCopyChildTransaction.AcceptChanges();

            DataTable dtCopyGrnTax = viewGrnTax.ToTable("dtCopyGrnTax", false, "GrnrPk", "ItemPk", "TaxComPk", "TaxPk", "TaxPer", "TaxRate", "Taxseq", "TaxDetAmt", "BTaxDetAmt");

            if (FormMode == Modes.New || FormMode == Modes.Edit || FormMode == Modes.Approve)
            {
                bool isSuccess = commonRulesObj.MultipleLineTaxCalculation(dtTranDet: ref dtCopyChildTransaction, dtTaxDetailTable: ref dtCopyGrnTax, curRate: Convert.ToDouble(CurrentRow["CurRate"]), whereCondition: "ItemPk<>0 AND PurPrice <> 0.00 AND qty <>0.00", keyFields: "ItemPk", totalTax: out totalTax, totAmount: out totAmount);
            }
            else
            {
                bool isSuccess = commonRulesObj.MultipleLineTaxCalculation(dtTranDet: ref  dtCopyChildTransaction, dtTaxDetailTable: ref dtCopyGrnTax, curRate: Convert.ToDouble(CurrentRow["CurRate"]), whereCondition: "ItemPk<>0 AND PurPrice <> 0.00 AND qty <>0.00", keyFields: "ItemPk", totalTax: out totalTax, totAmount: out totAmount, referenceNo: Convert.ToInt32(CurrentRow["GrnrPk"]), taxDetailTranTable: "fGrnTaxDt");
            }
                       
            CurrentRow["TotalTax"] = totalTax;
            CurrentRow["TotalAmt"] = totAmount;
            CurrentRow["TotalDis"] = sumTotalDiscount;
            this.OnPropertyChanged("CurrentRow");
        }

        private bool CheckItemStatus()
        {
            var masterReadService = new MasterReadService();
            var messageService = new MessageService();
            foreach (DataRow drGridData in DtChildTransaction.Rows)
            {
                string itemCode = Convert.ToString(drGridData["ItemCode"]);

                if (itemCode == string.Empty)
                {
                    continue;
                }
                else
                {
                    if (!masterReadService.IsItemActive(Convert.ToInt32(drGridData["ItemPk"])))
                    {
                        messageService.ShowMessage("Inactive item is selected. Please change to enter transactions.\nItem Code:" + itemCode, MessageType.InfoOK);
                        return false;
                    }
                }

            }
            return true;
        }

        private void ItemCodeGotFocusExecuted(object obj)
        {
            ItemCodeFilter = "RefNo =" + Convert.ToString(DtChildTransaction.Rows[GrnRowIndex]["RefNo"]); ;
            this.OnPropertyChanged("ItemCodeFilter");
        }


        protected override void PostDataInsertExecuted(object obj)
        {
            var transactionWriteService = new TransactionWriteService();

            var sqlTran = this.SqlTran;
           
            if (!transactionWriteService.UpdateGoodReceiveReturnSpecificData(CurrentRow,  DtChildTransaction,ref sqlTran))
            {
                this.IsValid = false;
            }
            else
            {
                this.IsValid = true;
                this.SqlTran = sqlTran;
            }
        }

        protected override void PostDataUpdateExecuted(object obj)
        {
            var transactionWriteService = new TransactionWriteService();
            var sqlTran = this.SqlTran;
            if (!transactionWriteService.UpdateGoodReceiveReturnSpecificData(CurrentRow,  DtChildTransaction, ref sqlTran))
            {
                this.IsValid = false;
            }
            else
            {
                this.IsValid = true;
                this.SqlTran = sqlTran;
            }
        }
    }
}


